<?php

namespace App\Repositories;

use App\Http\Services\FeieyunService;
use App\Models\Printer;
use App\Models\PrinterTask;
use App\Models\PrinterTaskContent;
use Exception;

class PrinterRepository
{

    public function getList($filter = [], $pageNum = 2, $pageSize = 10): array
    {
        $res = Printer::query()
            ->when(!empty($filter['keywords']), function ($query) use ($filter) {
                return $query->where("title", "like", "%{$filter['keywords']}%");
            })
            ->orderBy("id", "desc")
            ->paginate($pageSize, "*", null, $pageNum)
            ->toArray();

        $res = filterPaginateData($res);

        foreach ($res['items'] as $k => &$v) {
            $v['shop_title'] = Supplier::query()->where("id", intval($v['shop_id']))->value("title");
        }

        return $res;
    }

    public function getOne($id = 0)
    {
        return Printer::query()->where(['id' => intval($id)])->first();
    }

    public function saveOrUpdate($data = [], $id = 0)
    {
        if (!empty($data['id']))
            unset($data['id']);

        if (intval($id)) {
            Printer::where("id", $id)->update($data);
            return $id;
        } else {
            $res = Printer::create($data);
            return $res['id'] ?? "";
        }
    }

    /**
     * 删除
     * @param null $id
     */
    public function deletePrinter($id = null)
    {
        if (!intval($id))
            return retFail("参数错误");

        $res = Printer::query()->where(['id' => $id])->first();

        if (!isset($res))
            return retFail("打印机不存在");

        //权限 - 店铺角色是否权限
        (new FeieyunService(['id' => $id]))->delPrinterSqs();
        PrinterTask::query()->where(['printer_sn' => $id])->delete();
        Printer::query()->where(['id' => intval($id)])->delete();

        return retSuc([], "删除成功");
    }

    /**
     * 清空正在打印的
     * @param null $id
     */
    public function clearPrinter(int $id = 0)
    {
        if (!$id)
            return retFail("参数错误");

        $printer = $this->getOne($id);
        if (!isset($printer))
            return retFail("打印机不存在");

        $_printer = new FeieyunService(['id' => $id]);
        $res = $_printer->clearMsg();

        if ($res)
            return retSuc([], "清空成功");

        return retFail("清空失败");
    }

    /**
     * 初始化打印机
     * @param null $id
     */
    public function initPrinter(int $id = 0)
    {
        if (!$id)
            return retFail("参数错误");

        $printer = $this->getOne($id);
        if (!isset($printer))
            return retFail("打印机不存在");

        $feie = new FeieyunService(['id' => $id]);
        $glist = array(
            'orderid' => '4-14F',
            'keshi' => "耳鼻喉科",
            'remark' => '不要加辣！！！',
            'name' => '张三先生',
            'tel' => '13800138000',
            'z_number' => '五号桌',
            'goods' => array(
                '0' => array('title' => '可乐鸡翅', 'price' => '100.4', 'num' => '10')
            ),
        );

        $num = count($glist['goods']);
        $i = 1;
        $content = '';
        try {
            foreach ($glist['goods'] as $key => $value) {
                $content = '<DIRECTION>0</DIRECTION>';
                $content .= '<SIZE>50,80</SIZE>'; //新打印机需要初始化尺寸
                $content .= '<TEXT x="20" y="50" font="12" w="2" h="2" r="0">' . $this->Label_LR($glist['orderid'], "职工", 16) . '</TEXT>';
                $content .= '<TEXT x="20" y="110" font="12" w="2" h="2" r="0">' . $this->Label_LR($glist['keshi'], ($i . '/' . $num), 16) . '</TEXT>';

                $content .= '<TEXT x="20" y="130" font="12" w="1" h="1" r="0"></TEXT>';
                $content .= '<TEXT x="20" y="180" font="12" w="1" h="1" r="0">' . $glist['name'] . '    ' . $glist['tel'] . '</TEXT>';

                $content .= '<TEXT x="20" y="220" font="12" w="1" h="1" r="0">----------------------------------</TEXT>';
                $content .= '<TEXT x="20" y="270" font="12" w="2" h="2" r="0">' . $value["title"] . '</TEXT>';

                $content .= '<TEXT x="20" y="470" font="12" w="1" h="1" r="0">----------------------------------</TEXT>';
                $content .= '<TEXT x="20" y="520" font="12" w="2" h="2" r="0">' . $glist['remark'] . '</TEXT>';

                $i += 1;
                // printLabelMsg(XXXXXXXXX,$content,1);//打开注释调用标签打印接口打印
                $feie->printLabelMsg($content, 1);
            }

            return retSuc([], "初始化成功");
        } catch (Exception $e) {
            return retFail($e->getMessage() || "初始化失败");
        }
    }

    /**
     * 普通打印机
     * [统计字符串字节数补空格，实现左右排版对齐]
     * @param  [string] $str_left    [左边字符串]
     * @param  [string] $str_right   [右边字符串]
     * @param  [int]    $length      [输入当前纸张规格一行所支持的最大字母数量]
     *                               58mm的机器,一行打印16个汉字,32个字母;76mm的机器,一行打印22个汉字,33个字母,80mm的机器,一行打印24个汉字,48个字母
     *                               标签机宽度50mm，一行32个字母，宽度40mm，一行26个字母
     * @return [string]              [返回处理结果字符串]
     */
    function LR($str_left, $str_right, $length)
    {
        if (empty($str_left) || empty($str_right) || empty($length)) return '请输入正确的参数';
        $kw = '';
        $str_left_lenght = strlen(iconv("UTF-8", "GBK//IGNORE", $str_left));
        $str_right_lenght = strlen(iconv("UTF-8", "GBK//IGNORE", $str_right));
        $k = $length - ($str_left_lenght + $str_right_lenght);
        for ($q = 0; $q < $k; $q++) {
            $kw .= ' ';
        }
        return $str_left . $kw . $str_right;
    }


    /**
     * [统计字符串字节数补空格，实现左右排版对齐]
     * @param  [string] $str_left    [左边字符串]
     * @param  [string] $str_right   [右边字符串]
     * @param  [int]    $length      [输入当前纸张规格一行所支持的最大字母数量]
     *                               58mm的机器,一行打印16个汉字,32个字母;76mm的机器,一行打印22个汉字,33个字母,80mm的机器,一行打印24个汉字,48个字母
     *                               标签机宽度50mm，一行32个字母，宽度40mm，一行26个字母
     * @return [string]              [返回处理结果字符串]
     */
    function Label_LR($str_left, $str_right, $length)
    {
        if (empty($str_left) || empty($str_right) || empty($length)) return '请输入正确的参数';
        $kw = '';
        $str_left_lenght = strlen(iconv("UTF-8", "GBK//IGNORE", $str_left));
        $str_right_lenght = strlen(iconv("UTF-8", "GBK//IGNORE", $str_right));
        $k = $length - ($str_left_lenght + $str_right_lenght) - 1;
        for ($q = 0; $q < $k; $q++) {
            $kw .= ' ';
        }
        return $str_left . $kw . $str_right;
    }

    /**
     * 打印任务
     */
    public function getTasks($filter = [], $pageNum = 2, $pageSize = 10): array
    {

        $res = PrinterTask::query()
            ->from("printer_task as pt")
            ->join("printer as p", "p.id", "=", "pt.printer_sn")
            ->join("supplier as s", "s.id", "=", "pt.shop_id")
            ->orderBy("pt.id", "desc")
            ->paginate($pageSize, ["pt.*", "s.title as shop_title", "p.title as printer_title"], null, $pageNum)
            ->toArray();

        return filterPaginateData($res);
    }

    public function getOptions(int $shop_id = 0, $type = 1)
    {
        return Printer::query()
            ->when($shop_id, function ($q) use ($shop_id) {
                return $q->where('shop_id', $shop_id);
            })
            ->where(['status' => 1, 'type' => $type])
            ->orderBy("id", 'desc')
            ->get(['id', 'title'])
            ->toArray();
    }

    /**
     * 打印品单
     * @param array $orderIds
     * @param null $printerId
     * @param null $task_id
     * @param array $stall_ids
     */
    public function printerLabel($filter, $printerId = null, $type = 0)
    {

        $orderRepo = new OrderRepository();
        if ($type == 2) {//单个打印
            $orderIds = $filter['orderId'] ?? null;
            if (empty($orderIds))
                return retFail("请传入订单号");
            settype($orderIds, 'array');
        } else if ($type == 1) { //后台
            $orderIds = (new \App\Repositories\Manage\OrderRepository())->getOrderIdsFilter($filter);
        } else {
            $orderIds = $orderRepo->getOrderIdsByFilter($filter);
        }

        $task_data['title'] = "品单打印_" . "" . date("hi");
        $task_data['printer_sn'] = $printerId;
        $task_data['printer_type'] = 2;
        $task_data['supplier_id'] = $filter['shop_id'];
        $task_data['amount'] = count($orderIds);

        $task_id = null;
        if ($task_data['amount'] > 1) {
            $task_id = PrinterTask::create($task_data)->id;
        }

        foreach ($orderIds as $orderId) {
            $order = $orderRepo->getByOutTradeNo($orderId, true);
            $products = [];
            foreach ($order["products"] as $pk => $pv) {
                if (empty($filter['stall_id']) || in_array($pv['stall_id'], $filter['stall_id'])) {
                    $products[] = $pv;
                }
            }

            if (count($products) == 0) continue;
            $this->_printer_label($order, $products, $printerId, $task_id);
        }
        return retSuc();
    }

    private function _printer_label($order, $products = [], $printer_id = 0, $task_id = 0)
    {
        $shop_title = $order['shop']['title'];
        $title = $order['address']['province'] . '-' . $order['address']['city'];

        foreach ($products as $k => $v) {
            $p_amount = intval($v['amount']);
//            if ($v["type"] != 1 || empty($v['skus'])) continue;
            for ($k = 1; $k <= $p_amount; $k++) {
                $content = '<DIRECTION>0</DIRECTION>';
//                $content .= '<TEXT x="20" y="50" font="12" w="2" h="2" r="0">' . $this->Label_LR($title, $shop_title ? $shop_title : ' ', 16) . '</TEXT>';
                $content .= '<TEXT x="20" y="50" font="12" w="2" h="2" r="0">' . $this->Label_LR($title, ' ', 16) . '</TEXT>';
                $total_str = $p_amount > 1 ? ($k . '/' . $p_amount) : ' ';
                $content .= '<TEXT x="20" y="110" font="12" w="1" h="2" r="0">' . $this->Label_LR($order['address']['region'], $total_str, 30) . '</TEXT>';
                $content .= '<TEXT x="20" y="130" font="12" w="1" h="1" r="0"></TEXT>';
                $content .= '<TEXT x="20" y="180" font="12" w="1" h="1" r="0">' . $order['address']['consignee'] . '  ' . maskPhone($order['address']['phone']) . '</TEXT>';
                // $content .= '<TEXT x="20" y="230" font="12" w="1" h="1" r="0">订单号：' . $order["out_trade_no"] . '</TEXT>';

                $content .= '<TEXT x="20" y="230" font="12" w="1" h="1" r="0">----------------------------------</TEXT>';
                $content .= '<TEXT x="20" y="280" font="12" w="2" h="2" r="0">' . msubstr($v["title"], 0, 8, "utf-8", false) . '</TEXT>';

                $sy = 340;
                if (strlen_utf8($v['title']) > 8) {
                    $content .= '<TEXT x="20" y="' . $sy . '" font="12" w="2" h="2" r="0">' . msubstr($v["title"], 8, strlen_utf8($v['title']) + 1, "utf-8", false) . '</TEXT>';
                    $sy += 40;
                }

                $sy += 20;
                if ($v['type'] == 2) { //多规格
                    $str = "";
                    foreach ($v['skus'] as $sk => $sv) {
                        $str1 = $sv['spec_item_title'];
                        if (strlen($str) + strlen($str1) > 40) {
                            $content .= '<TEXT x="20" y="' . $sy . '" font="12" w="1" h="1" r="0">' . $str . '</TEXT>';
                            $str = $str1;
                            $sy += 35;
                            continue;
                        }
                        $str .= $str1 . " ";
                    }

                    if ($str)
                        $content .= '<TEXT x="20" y="' . $sy . '" font="12" w="1" h="1" r="0">' . $str . '</TEXT>';

                } else if ($v['type'] == 1) { //套餐
                    $seq_arr = [];
                    foreach ($v['skus'] as $pk => $pv) { //套餐
                        for ($i = 0; $i < $pv['amount']; $i++) {
                            $seq_arr[] = $pv['sequence'];
                        }
                    }
                    $content .= '<TEXT x="20" y="' . $sy . '" font="12" w="2" h="2" r="0">' . implode("-", $seq_arr) . '</TEXT>';

                    $str = "";
                    $sy += 60;
                    foreach ($v['skus'] as $sk => $sv) {
                        $str1 = $sv['spec_item_title'] . ' x' . $sv['amount'];
                        if (strlen($str) + strlen($str1) > 40) {
                            $content .= '<TEXT x="20" y="' . $sy . '" font="12" w="1" h="1" r="0">' . $str . '</TEXT>';
                            $str = $str1;
                            $sy += 35;
                            continue;
                        }
                        $str .= $str1 . " ";
                    }

                    if ($str) {
                        $content .= '<TEXT x="20" y="' . $sy . '" font="12" w="1" h="1" r="0">' . $str . '</TEXT>';
                    }
                }

                $sy += 40;
                $content .= '<TEXT x="20" y="' . $sy . '" font="12" w="1" h="1" r="0">----------------------------------</TEXT>';
                if (!empty($order['buyer_remark'])) {
                    $sy += 50;

                    $buyer_remark = array_filter(explode(",", str_replace("，", ",", $order['buyer_remark'])));
                    if (count($buyer_remark) > 1) {
                        foreach ($buyer_remark as $bk => $bv) {
                            $content .= '<TEXT x="20" y="' . $sy . '" font="12" w="2" h="2" r="0">' . $bv . '</TEXT>';
                            $sy += 60;
                        }
                    } else {
                        $content .= '<TEXT x="20" y="' . $sy . '"  font="12" w="2" h="2" r="0">' . msubstr($order["buyer_remark"], 0, 8, "utf-8", false) . '</TEXT>';
                        if (strlen_utf8($order["buyer_remark"]) > 8) {
                            $sy += 50;
                            $content .= '<TEXT x="20" y="' . $sy . '" font="12" w="2" h="2" r="0">' . msubstr($order["buyer_remark"], 8, strlen_utf8($order["buyer_remark"]) + 1, "utf-8", false) . '</TEXT>';
                        }
                    }
                }

                if (!empty($order['callNo'])) {
                    $sy += 40;
                    $content .= '<TEXT x="20" y="' . $sy . '" font="12" w="2" h="2" r="0">序号：' . $order['callNo'] . '</TEXT>';
                }

                if ($task_id && $order['shop']['open_printer_task']) {
                    PrinterTaskContent::create([
                        'order_id' => $order['id'],
                        'task_id' => $task_id,
                        'supplier_id' => $order['shop_id'] ?? 0,
                        'content' => $content,
                        'printer_id' => $printer_id
                    ]);
                } else {
                    (new FeieyunService(['id' => $printer_id]))->printLabelMsg($content, $order['id']);
                }
            }
        }

        return true;
    }

    /**
     * 打印订单 （档口 / 订单/科室）
     * @param array $print_data
     * @param null $printer_id
     * @param null $task_id
     * @return bool
     */
    public function printOrder($print_data = [], $condition = [], $task_id = null)
    {

        $content = "<B>" . ($print_data['shop_title'] ?? "") . "</B><BR>";
        $content .= "<B>" . $this->LR($print_data['province'] . '-' . $print_data['city'] . 'F', " ", 24) . "</B><BR>";
        $content .= "<B>" . $print_data['region'] . $print_data['district_title'] . ($print_data['address'] ? ("-" . $print_data['address']) : '') . "</B><BR>";
        $content .= '------------------------------------------------<BR>';
        if ($print_data['delivery_date']) {
            $content .= "<B>" . $print_data['delivery_date'] . " " . $print_data['callNo'] . "</B><BR>";
        } else if ($print_data['title']) {
            $content .= "<B>" . $print_data['title'] . " " . $print_data['callNo'] . "</B><BR>";
        } else if ($print_data['shop_type'] == 1) {
            $content .= "<B>" . date("m月d日", strtotime($condition['menu']['date'])) . " " . menu_type($condition['menu']['type']) . " " . $print_data['callNo'] . "</B><BR>";
        }
        $content .= '------------------------------------------------<BR>';

        foreach ($print_data['products'] as $k => $v) {
            $price = $v['amount'] * $v['price'];
            if ($v['combo_title']) {
                $content .= "<L>" . $v['title'] . " (" . $v['combo_title'] . ")</L><BR>";
            } else {
                $content .= "<L>" . $v['title'] . "</L><BR>";
            }
            $content .= "<RIGHT><L>" . $this->LR('  ', ($v['amount'] > 1 ? ("【" . $v['amount'] . "】") : $v['amount']) . "份  " . $price . "元 ", 24) . "</RIGHT></L>";
        }

        $content .= '<BR>------------------------------------------------<BR>';
        $content .= "<B>" . $this->LR('  ', "共" . $print_data['total_price'] . "元", 24) . "</B><BR>";
        $content .= "<RIGHT><L>" . $this->LR('  ', "总份数：" . $print_data['product_amount'], 24) . "</L></RIGHT>";
        $content .= '------------------------------------------------<BR>';
        if ($print_data['order_source'] == 1) {
            $content .= "<B>！未付款，请线下支付</B><BR>";
            $content .= '<BR>------------------------------------------------<BR>';
        }
        if ($print_data['buyer_remark']) {
            $content .= "<B>" . $print_data['buyer_remark'] . "</B><BR>";
            $content .= '<BR>------------------------------------------------<BR>';
        }
        $content .= "<L>" . $print_data['consignee'] . '  ' . maskPhone($print_data['phone']) . "</L><BR>";
        $content .= '------------------------------------------------<BR>';
//        $content .= "<BR><BOLD>开始时间：" . substr($condition['menu']['start_time'], 0, 16) . "</BOLD><BR>";
//        $content .= "<BOLD>结束时间：" . substr($condition['menu']['end_time'], 0, 16) . "</BOLD><BR><BR>";
        $content .= "<L>订单号：" . $print_data['out_trade_no'] . "</L><BR>";

        if (!($condition['is_printer_now'] ?? 0) && $task_id && $print_data["open_printer_task"]) {
            PrinterTaskContent::create([
                'order_id' => $print_data['id'],
                'task_id' => $task_id,
                'supplier_id' => $print_data['shop_id'] ?? 0,
                'content' => $content,
                'printer_id' => $condition['printer_id']
            ]);
        } else {
            (new FeieyunService(['id' => intval($condition['printer_id'])]))->printMsg($content, $print_data['id']);
        }
        return true;
    }

    /**
     * 打印档口
     * @param $printer_id
     * @param array $print_data
     * @param null $shop_title
     * @return bool|void
     */
    public function printStallOrder($print_data = [], $printer_id, $shop = null)
    {
        if (empty($shop))
            throw new Exception("店铺不存在");

        if (empty($print_data) || count($print_data) == 0) {
            throw new Exception("订单不能为空");
        }

        $task_data['title'] = "档口打印_" . date("hi");
        $task_data['printer_sn'] = $printer_id;
        $task_data['printer_type'] = 3; //档口
        $task_data['supplier_id'] = $shop['id'] ?? 0;

        $print_data = ass_column($print_data, "stall_id", true);
        $task_data['amount'] = count($print_data);

        $taksk_id = null;
        if ($task_data['amount'] > 1) {
            $task_id = PrinterTask::create($task_data)->id;
        }

        $is_printer_now = count($print_data) <= 1 ? 1 : 0;
        foreach ($print_data as $k => $v) {
            $menu = ass_column($v, "menu_id", true);

            foreach ($menu as $sk => $sv) {
                $content = "<B>{$shop['title']}</B><BR><BR>";
                $content .= "<B>档口菜品制作-汇总单</B><BR><BR>";
                $content .= "<B>档口：" . $v[0]['stall_title'] . "</B><BR><BR>";
                $content .= "<B>" . $sv[0]['menu_title'] . "</B><BR><BR>";
                $content .= '------------------------------------------------<BR><BR>';
                $content .= "<B>菜单数：" . array_sum(get_column($sv, "amount")) . "份</B><BR><BR>";
                foreach ($sv as $ssk => $ssv) {
                    $content .= "<B>" . $ssv['product_title'] . "x" . $ssv['amount'] . "</B><BR><BR>";
                    if (in_array($ssv['type'], [1, 2])) {
                        $content .= "" . $ssv['skuTxt'] . "<BR><BR>";
                    }
                }

                $content .= '------------------------------------------------<BR><BR>';
                $content .= '<BOLD>完成制作后，菜品盒盖上清晰标注送至相应分拣区。</BOLD><BR><BR>';

                if (!$is_printer_now && $task_id && $shop['open_printer_task']) {
                    PrinterTaskContent::create([
                        'order_id' => $v['order_id'],
                        'task_id' => $task_id,
                        'supplier_id' => $shop['id'] ?? 0,
                        'content' => $content,
                        'printer_id' => $printer_id
                    ]);
                } else {
                    (new FeieyunService(['id' => $printer_id]))->printMsg($content, $v['order_id']);
                }
            }
        }

        return true;
    }

    /**
     * 打印科室
     * @param $printer_id
     * @param array $print_data
     * @param null $shop_title
     */
    function printerKs($print_data = [], $condition = [], $task_id = null)
    {
        $content = "<B>【【【科室汇总单】】】</B><BR>";
        $content .= "<B>【【【科室汇总单】】】</B><BR><BR>";

        if ($condition['menu_title']) {
            $content .= "<B>" . $condition['menu_title'] . "</B><BR>";
        } else {
            $content .= "<B>" . date("m月d日", strtotime($condition['menu']['date'])) . "  " . menu_type($condition['menu']['type']) . "</B><BR>";
        }

        $content .= "<B>" . $this->LR($print_data['province'] . '-' . $print_data['city'], $condition['shop_title'], 24) . "</B><BR>";
        $content .= "<B>" . $this->LR($print_data['region'], ' ', 24) . "</B>";
        $content .= '<L></L>----------------------------------------------<BR>';
        $content .= "<L>" . "总份数：" . $print_data['product_amount'] . "</L><BR>";
        $content .= "<L>" . "总订单数：" . $print_data['order_amount'] . "</L><BR>";
        $content .= '------------------------------------------------<BR>';
        foreach ($print_data['products'] as $k => $v) {
            $content .= "<B>" . $v['title'] . "</B><BR>";
            $content .= "<B>" . $this->LR('  ', ($v['amount'] > 1 ? ("【" . $v['amount'] . "】") : $v['amount']) . " 份", 24) . "</B>";
        }
        $content .= '<BR><BR>------------------------------------------------<BR><BR>';
        if ($print_data['unpaid']) {
            $content .= "<B>有未付款订单，</B><BR>";
            $content .= "<B>请线下支付</B><BR>";
            $content .= '------------------------------------------------<BR>';
        }
        $content .= '<BOLD>请根据订单配送！完成配送在小程序确认。</BOLD><BR>';
        $content .= "<BR>开始时间：" . substr($condition['menu']['start_time'], 0, 16) . "<BR>";
        $content .= "结束时间：" . substr($condition['menu']['end_time'], 0, 16) . "<BR>";


        if ($task_id && $print_data['open_printer_task']) {
            PrinterTaskContent::create([
                'order_id' => $v['order_id'],
                'task_id' => $task_id,
                'supplier_id' => $condition['shop_id'] ?? 0,
                'content' => $content,
                'printer_id' => $condition['printer_id']
            ]);

        } else {
            (new FeieyunService(['id' => $condition['printer_id']]))->printMsg($content, $v['order_id']);
        }

        return true;
    }


}
